Imports atcMwGisUtility

Public Class frmMainMW

    Private Enum enumField
        ID
        Name
        Type
        Freq
        Lat
        Lon
        Elev
        Branch
        Reach
        RMile
        Area
        Agency
        RefID
        Remarks
        Other
        HUC
    End Enum

    ''' <summary>
    ''' Controls how data are displayed in GIS form
    ''' </summary>
    Public Enum enumMode
        ''' <summary>Display all stations from support table</summary>
        Display
        ''' <summary>Select from all stations found in browser</summary>
        [Select]
        ''' <summary>Display summary from last query</summary>
        Output
    End Enum

    Private ActiveLayer As Graph.clsLayer
    Private dtResults As DataTable
    Private dwgHandle As Integer

    Friend GISProjectPath As String
    Private HasBeenQueried As Boolean
    Private IsSelecting As Boolean = False
    Private lstCoords As New Generic.List(Of Point)
    Private lstStations As New Generic.List(Of String)

    Friend Mode As enumMode
    Private Modified As Boolean = False
    Private MustFillLists As Boolean = False
    Private MustSummarize As Boolean = False
    Private MustCreateLayer As Boolean = False

    ''' <summary>
    ''' List of station IDs currently selected on GIS map
    ''' </summary>
    ''' <remarks></remarks>
    Friend SelectedStations As New Generic.List(Of String)
    Private WRDBLayerHandle As Integer
    Private WRDBShapefile As MapWinGIS.Shapefile

    ''' <summary>
    ''' Used to find the data row associated with the station that was just clicked on
    ''' </summary>
    ''' <param name="ScreenX">X Mouse click position in pixels</param>
    ''' <param name="ScreenY">Y Mouse click position in pixels</param>
    ''' <returns>Datarow containing station clicked on (or Nothing if didn't click close enough)</returns>
    Private Function FindShapes(ByVal ScreenX As Integer, ByVal ScreenY As Integer) As Generic.List(Of Integer)
        Const WindowSize As Integer = 5
        Dim lst As New Generic.List(Of Integer)

        With WRDBShapefile
            'following cache speeds up search--only computed when extents change
            If lstCoords.Count = 0 Then
                For r As Integer = 0 To .NumShapes - 1
                    With .Shape(r)
                        Dim x, y As Double
                        MainWRDB.GISMap.ProjToPixel(.Point(0).x, .Point(0).y, x, y)
                        lstCoords.Add(New Point(x, y))
                    End With
                Next
            End If

            For r As Integer = 0 To lstCoords.Count - 1
                If r > lstCoords.Count - 1 Then Return lst
                Dim p As Point = lstCoords(r)
                If Mode = enumMode.Output Then
                    If Math.Abs(ScreenX - p.X) < WindowSize AndAlso Math.Abs(ScreenY - p.Y) < WindowSize Then lst.Add(r)
                Else
                    If (cboDisplay.SelectedIndex = 0 OrElse cboDisplay.Text = TestNull(.CellValue(enumField.Type, r), "")) AndAlso _
                        Math.Abs(ScreenX - p.X) < WindowSize AndAlso Math.Abs(ScreenY - p.Y) < WindowSize Then lst.Add(r)
                End If
            Next
        End With
        Return lst
    End Function

    Private Function SelectedStationList() As String

        If WRDBShapefile Is Nothing Then Return "Please refresh the display first..."

        Dim txt As String = "Current WRDB Project: " & Project.Name & vbCrLf & vbCrLf
        txt &= "Currently selected stations:"

        SelectedStations.Clear()
        With MainWRDB.MapWin.View.SelectedShapes
            If .NumSelected = 0 Then
                txt &= vbCrLf & "    (None)"
            Else
                For i As Integer = 0 To .NumSelected - 1
                    Dim StationID As String = WRDBShapefile.CellValue(enumField.ID, .Item(i).ShapeIndex)
                    txt &= vbCrLf & "    " & StationID
                    SelectedStations.Add(StationID)
                Next
            End If
        End With

        Return txt & vbCrLf & "==============="
    End Function

    ''' <summary>
    ''' Execute query so that the same data you select on map are available for reports, etc.
    ''' </summary>
    Private Sub ExecuteQuery()
        Dim SQL As String = String.Format("SELECT * FROM {0} WHERE PCODE='{1}'", ActiveBrowser.TableName, StringSplit(cboPCode.Text, " - ")(0))
        If Not cboCCode.Text.StartsWith("(") Then SQL &= String.Format(" AND CCode='{0}'", StringSplit(cboCCode.Text, " - ")(0))
        If Not txtDateTime.Text.StartsWith("(") Then SQL &= " AND " & IIf(txtDateTime.Text.ToUpper.Contains("DATE_TIME"), "", "Date_Time ") & txtDateTime.Text
        With MainWRDB.MapWin.View.SelectedShapes
            If .NumSelected > 0 Then
                Dim StationList As String = ""
                For i As Integer = 0 To .NumSelected - 1
                    Dim StationID As String = WRDBShapefile.CellValue(enumField.ID, .Item(i).ShapeIndex)
                    StationList &= IIf(StationList = "", "", ",") & "'" & StationID & "'"
                    SelectedStations.Add(StationID)
                Next
                SQL &= " AND Station_ID IN (" & StationList & ")"
            End If
        End With
        MainForm.SelectData(SQL)
    End Sub

    Private Sub btnDateTime_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnDateTime.Click
        Try
            With New frmQueryAssist(ActiveBrowser.FullTableName, "Date_Time", frmQueryAssist.enumAssist.DateTimeValue)
                If .ShowDialog(Me) = Windows.Forms.DialogResult.OK Then
                    txtDateTime.Text = .QueryString
                    SummarizeStationData()
                    btnRefresh.Enabled = True
                    If chkRefresh.Checked Then RefreshDisplay()
                End If
                .Dispose()
            End With
        Catch ex As Exception
            ErrorMsg(, ex)
        End Try
    End Sub

    Private Sub btnRefresh_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnRefresh.Click
        Try
            If MustCreateLayer Or WRDBShapefile Is Nothing Or Not GisUtil.IsLayer(MainWRDB.WRDBLayerName) Then
                CreateLayer()
            End If
            If Mode = enumMode.Output Then
                If MustFillLists Then FillLists()
                If MustSummarize Then SummarizeStationData()
            End If
            RefreshDisplay()
        Catch ex As Exception
            ErrorMsg(, ex)
        End Try
    End Sub

    Private Sub cbo_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles cboDisplay.SelectionChangeCommitted
        Try
            Application.DoEvents()
            'only recreate if changed mode from displaying results to stations
            If Mode = enumMode.Display Then
                MustCreateLayer = True
            Else
                If (cboDisplay.SelectedIndex = 0 And grpPCode.Enabled) Or (cboDisplay.SelectedIndex <> 0 And Not grpPCode.Enabled) Then MustCreateLayer = True
                If cboDisplay.SelectedIndex <> 0 And MustFillLists Then FillLists()
            End If
            grpPCode.Enabled = (Mode = enumMode.Output) And (cboDisplay.SelectedIndex > 0)
            btnRefresh.Enabled = True
            If chkRefresh.Checked Then btnRefresh.PerformClick()
        Catch ex As Exception
            ErrorMsg(, ex)
        End Try
    End Sub

    Private Sub cboPCode_SelectionChangeCommitted(ByVal sender As Object, ByVal e As System.EventArgs) Handles cboPCode.SelectionChangeCommitted
        Try
            Application.DoEvents()
            MustSummarize = True
            btnRefresh.Enabled = True
            If chkRefresh.Checked Then btnRefresh.PerformClick()
        Catch ex As Exception
            ErrorMsg(, ex)
        End Try
    End Sub

    Private Sub cboCCode_SelectionChangeCommitted(ByVal sender As Object, ByVal e As System.EventArgs) Handles cboCCode.SelectionChangeCommitted
        Try
            SummarizeStationData()
            btnRefresh.Enabled = True
            If chkRefresh.Checked Then RefreshDisplay()
        Catch ex As Exception
            ErrorMsg(, ex)
        End Try
    End Sub

    Private Sub chkRefresh_CheckedChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles chkRefresh.CheckedChanged
        Try
            If chkRefresh.Checked Then
                If Mode <> enumMode.Display Then FillLists()
                If btnRefresh.Enabled Then btnRefresh.PerformClick()
                btnRefresh.Enabled = False
            End If
        Catch ex As Exception
            ErrorMsg(, ex)
        End Try
    End Sub

    Public Sub Consolidate()
        With New frmConsolidate(dtResults)
            .ShowDialog()
            .Dispose()
        End With
    End Sub

    ''' <summary>
    ''' Called when user has executed a query in WRDB and it has completed: update thematic map with results by recreating a shp file
    ''' </summary>
    Friend Sub CreateLayer()

        Dim mwCallback As New clsMWCallback

        'first remove all existing WRDB stations layers

        If GisUtil.IsLayer(MainWRDB.WRDBLayerName) Then GisUtil.RemoveLayer(GisUtil.LayerIndex(MainWRDB.WRDBLayerName))
        Application.DoEvents()

        If WRDBShapefile Is Nothing Then
            WRDBShapefile = New MapWinGIS.Shapefile
        Else
            WRDBShapefile.Close()
        End If
        Dim drStations As DbDataReader = Nothing
        Try
            MainForm.WriteProgress("Creating shape file...", ProgressBarStyle.Marquee)
            Dim SQL As String
            Dim NumStations As Integer = 0
            With Project
                Dim TableName As String = ""
                If ActiveBrowser IsNot Nothing Then TableName = IIf(Mode = enumMode.Select Or IsMWForm, ActiveBrowser.TableName, clsProject.TempData)
                Dim LatLonClause As String = "LATITUDE<>0.0 AND LONGITUDE<>0.0"
                Select Case Mode
                    Case enumMode.Output, enumMode.Select
                        Dim PCodeClause As String = ""
                        'If cboPCode.Enabled Then PCodeClause = String.Format(" AND PCODE = '{0}'", StringSplit(cboPCode.Text, " - ")(0))
                        'SQL = String.Format("SELECT DISTINCT Stations.* FROM Stations,{0} Dta WHERE {1} AND Dta.Station_ID=Stations.Station_ID{2}", TableName, LatLonClause, PCodeClause)
                        If cboPCode.Enabled Then PCodeClause = String.Format(" WHERE PCODE = '{0}'", StringSplit(cboPCode.Text, " - ")(0))
                        SQL = String.Format("SELECT DISTINCT Stations.* FROM Stations WHERE {1} AND Station_ID IN (SELECT DISTINCT Station_ID FROM {0}{2})", TableName, LatLonClause, PCodeClause)
                        .ResetPDox(ActiveBrowser.TableName)
                        .CopyPDoxSupportTables(.GetTableType(ActiveBrowser.TableName), clsProject.enumTableTypes.Stations)
                    Case Else
                        Dim TypeClause As String = ""
                        If Not cboDisplay.Text.StartsWith("(") Then TypeClause = String.Format(" AND Station_Type='{0}'", cboDisplay.Text)
                        SQL = String.Format("SELECT * FROM Stations WHERE {0}{1}", LatLonClause, TypeClause)
                        .ResetPDox(clsProject.enumTableTypes.Stations)
                End Select
                'don't need either one--only used to write progress, and that is so fast there is no need to waste time here
                'NumStations = .DB.ExecuteScalar("SELECT COUNT(*) FROM ({0})", SQL)
                'NumStations = .DB.ExecuteScalar("SELECT COUNT(*) FROM (SELECT DISTINCT Station_ID FROM {0})", tablename) 'this will also return stations with empty lat/long, but avoids JOIN

                Dim start As Date = Now

                drStations = .DB.ExecuteReader(SQL)

                Static AlreadyWarned As Boolean = False
                If Not AlreadyWarned AndAlso Not MainWRDB.ExpertMode AndAlso Now.Subtract(start).TotalSeconds > 15 AndAlso ActiveBrowser IsNot Nothing AndAlso Project.DB.GetIndexList(ActiveBrowser.TableName).Count = 0 AndAlso Project.QueryOption = clsProject.enumQueryOption.View Then
                    WarningMsg("This layer took a long time to create. You can speed up performance by indexing the table by Station_ID and PCode (using File | Database Explorer).\n\nThis suggestion will not be repeated this session.")
                    AlreadyWarned = True
                End If

            End With

            'delete existing shp files and create and add new one

            Dim NumShapes As Integer = 0

            With WRDBShapefile
                Dim FileName As String = MainWRDB.WRDBShapeDirectory & "\WRDB Stations.shp"
                Try
                    For i As Int16 = 1 To 5
                        Dim ext As String = Choose(i, "shp", "shx", "dbf", "prj", "mwsr")
                        Dim fn As String = IO.Path.ChangeExtension(FileName, ext)
                        Try
                            If My.Computer.FileSystem.FileExists(fn) Then My.Computer.FileSystem.DeleteFile(fn)
                        Catch ex As Exception
                        End Try
                        If My.Computer.FileSystem.FileExists(fn) Then
                            WarningMsgFmt("Unable to delete file: {0}; it may be locked by another program.", fn)
                            Exit Sub
                        End If
                    Next
                Catch ex As Exception
                End Try

                If drStations Is Nothing Then Exit Sub

                If Not My.Computer.FileSystem.DirectoryExists(IO.Path.GetDirectoryName(FileName)) Then My.Computer.FileSystem.CreateDirectory(IO.Path.GetDirectoryName(FileName))

                If .CreateNew(FileName, MapWinGIS.ShpfileType.SHP_POINT) Then
                    .StartEditingShapes(True)
                    '.StartEditingTable()

                    'add one field for each field in datatable
                    For i As Integer = 0 To IIf(Project.GisQuickTable, 2, Project.dsWRDB.Tables("Stations").Columns.Count - 1)
                        Dim c As DataColumn = Project.dsWRDB.Tables("Stations").Columns(i)
                        Dim fld As MapWinGIS.Field = New MapWinGIS.Field
                        fld.Name = c.ColumnName.Replace("Station", "Stat")
                        If c.DataType Is System.Type.GetType("System.String") Then
                            fld.Type = MapWinGIS.FieldType.STRING_FIELD
                            fld.Width = IIf(c.MaxLength = -1, 255, c.MaxLength)
                            If Project.GisQuickTable And c.ColumnName.ToUpper = "STATION_TYPE" Then fld.Width = 6 'doesn't need to be 60 characters!
                        ElseIf c.DataType Is System.Type.GetType("System.Integer") Then
                            fld.Type = MapWinGIS.FieldType.INTEGER_FIELD
                        Else
                            fld.Type = MapWinGIS.FieldType.DOUBLE_FIELD
                            fld.Precision = 5
                        End If
                        .EditInsertField(fld, .NumFields + 1, mwCallback)
                    Next

                    Dim rownum As Integer = 0

                    'if showing all station locations, create normal shape file with all stations; will add layer of normal points colored by station type
                    'if showing thematic map of values, shape file will contain only stations with data; symbol size will vary with specified field value

                    'Dim minx As Double = Double.MaxValue, maxx As Double = -minx
                    Dim StaRcd(drStations.FieldCount - 1) As Object
                    Dim t1 As Date = Now

                    MainForm.WriteProgress("Creating shape file...", ProgressBarStyle.Marquee)

                    While drStations.Read
                        drStations.GetValues(StaRcd)
                        Dim x As Single = -Math.Abs(TestNull(StaRcd(5), 0))
                        Dim y As Single = TestNull(StaRcd(4), 0)
                        If Math.Abs(x) > 1 And y > 1 And Math.Abs(x) < 180 And y < 90 Then
                            'minx = Min(minx, x)
                            'maxx = Max(maxx, x)
                            Dim pnt As New MapWinGIS.Point
                            pnt.x = x
                            pnt.y = y
                            Dim shp As New MapWinGIS.Shape
                            If shp.Create(MapWinGIS.ShpfileType.SHP_POINT) AndAlso shp.InsertPoint(pnt, 0) AndAlso .EditInsertShape(shp, .NumShapes) Then
                                For colnum As Integer = 0 To IIf(Project.GisQuickTable, 2, StaRcd.Length - 1)
                                    If Not IsDBNull(StaRcd(colnum)) Then
                                        Dim v As Object
                                        If TypeOf StaRcd(colnum) Is String Then
                                            v = CStr(StaRcd(colnum))
                                            If Project.GisQuickTable And colnum = 2 And CStr(v).Length >= 6 Then v = CStr(v).Substring(0, 6)
                                        ElseIf TypeOf StaRcd(colnum) Is Integer Then
                                            v = CInt(StaRcd(colnum))
                                        ElseIf TypeOf StaRcd(colnum) Is Date Then
                                            v = CDate(StaRcd(colnum))
                                        Else
                                            v = CDbl(StaRcd(colnum))
                                        End If
                                        .EditCellValue(colnum, .NumShapes - 1, v)
                                        'Debug.Print(v)
                                    End If
                                Next
                            Else
                                WarningMsg("Unable to create shape")
                                Exit While
                            End If
                        End If
                        rownum += 1
                        If Not MainForm.WriteProgress(rownum, NumStations, "Creating shape file...", ProgressBarStyle.Blocks, True) Then Exit While
                    End While

                    'MsgBox(Now.Subtract(t1).TotalSeconds)
                    MainForm.WriteProgress("Saving shape file...", ProgressBarStyle.Marquee, False)
                    .StopEditingShapes(True, True)
                    NumShapes = .NumShapes
                    .Projection = WRDB.Graph.LatLongProjection
                    .SaveAs(FileName)
                    .Close()

                    'need to reproject to the current setting for the MW project 

                    If NumShapes > 0 And WRDB.Graph.ProjectProjection <> "" And Not MainWRDB.GISMap.IsSameProjection(Graph.LatLongProjection, Graph.ProjectProjection) Then
                        MainForm.WriteProgress("Reprojecting shape file...", ProgressBarStyle.Marquee)
                        If Not WRDB.Graph.Reproject(MainWRDB.GISMap, FileName, WRDB.Graph.ProjectProjection, True) Then Exit Sub
                    End If
                Else
                    ErrorMsg(MainWRDB.GISMap.get_ErrorMsg(MainWRDB.GISMap.LastErrorCode))
                End If

                'shape file is created, now add to view

                MainForm.WriteProgress("Adding layer...", ProgressBarStyle.Marquee)
                Try
                    GisUtil.AddGroup(MainWRDB.WRDBGroupName)
                Catch ex As Exception
                End Try

                GisUtil.AddLayerToGroup(FileName, MainWRDB.WRDBLayerName, MainWRDB.WRDBGroupName)
                GisUtil.LayerVisible(MainWRDB.WRDBLayerName) = False 'will turn it on in RefreshDisplay
                ActiveLayer = Graph.clsLayer.Reset(MainWRDB.GISMap, MainWRDB.WRDBLayerName)
                With CType(ActiveLayer, Graph.clsLayerPoint)
                    .Name = MainWRDB.WRDBLayerName
                    .PointSize = 8
                    .PointType = MapWinGIS.tkPointType.ptTriangleDown
                    WRDBLayerHandle = .LayerHandle
                End With

                'reopen so is available elsewhere
                WRDBShapefile.Open(FileName)

            End With

        Catch ex As Exception
            ErrorMsg(, ex)
        Finally
            If drStations IsNot Nothing Then drStations.Close()
            'Me.ProgressBar.Visible = False
            MainForm.ProgressComplete()
            MustCreateLayer = False
        End Try
    End Sub

    Private Sub FillLists()
        WriteProgress("Filling lists...", ProgressBarStyle.Marquee)
        If Project.GisQuickList Then
            Project.DB.FillPickList(cboPCode, "", "PCodes", "PCode", "Anal_Name", "", , Project.SupportDir)
            Project.DB.FillPickList(cboCCode, "", "CCodes", "CCode", "CCode_Name", "(All)", , Project.SupportDir)
        Else
            Project.DB.FillPickList(cboPCode, ActiveBrowser.FullTableName, "PCodes", "PCode", "Anal_Name", "", , Project.SupportDir)
            Project.DB.FillPickList(cboCCode, ActiveBrowser.FullTableName, "CCodes", "CCode", "CCode_Name", "(All)", , Project.SupportDir)
        End If
        txtDateTime.Text = "(All)"
        lblInfo.Text = String.Format("Current WRDB Project: {0}\n\n", Project.Name).Replace("\n", vbCrLf)
        lblInfo.Text &= "Select the PCode (and CCode && Date range) of interest, then select the desired statistic to display. Select stations on the map to display time series graphs." & vbCrLf & vbCrLf & "When the Select tool is activated, you can select stations for further analysis on the screen, and when you position your mouse over a WRDB station, important statistics will appear in this window."
        MustFillLists = False
        ProgressComplete()
    End Sub

    Private Sub frmMain_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        If Not Me.DesignMode Then
            'always start up with it unchecked to speed up display
            chkRefresh.Checked = False
            'ResetAll()
            'individual browsers will have menus and toolbars, so hide selected ones here
            mnuEdit.Visible = False
            mnuSelect.Visible = False
            mnuOutput.Visible = False
            mnuWindow.Visible = False
            mnuHelpWhatsThis.Visible = False 'doesn't work in BASINS
            tbOpenProject.Visible = True
            tbPrefs.Visible = True
            tbExplore.Visible = True
            tbSepExplore.Visible = True
            tbNew.Visible = True
            tbOpenWorking.Visible = True
            tbOpenMaster.Visible = True
            tbOpenSupport.Visible = True
            tbHelp.Visible = True
            tbWhatsThis.Visible = True
            tbDeleteSelected.Visible = False
            tbExport.Visible = False
            tbGraphScatter.Visible = False
            tbGraphTS.Visible = False
            tbImportFile.Visible = False
            tbRptP.Visible = False
            tbRptS.Visible = False
            tbRptSP.Visible = False
            tbSave.Visible = False
            tbSelectAdv.Visible = False
            tbSelectAll.Visible = False
            tbSelectRng.Visible = False
            tbSelectShow.Visible = False
            tbSelectSQL.Visible = False
            tbSepOpenSupport.Visible = False
            tbSepSelect.Visible = False
            tbSepRpt.Visible = False
            tbSepGraph.Visible = False
            tbWhatsThis.Visible = False
            For i As Integer = 0 To Graph.DefaultLayerColor.Length - 1
                Graph.DefaultLayerColor(i) = Choose((i Mod 14) + 1, Color.Red, Color.Blue, Color.Green, Color.Cyan, Color.Magenta, Color.DarkOrange, Color.Gray, Color.Black, Color.DarkRed, Color.DarkBlue, Color.DarkGreen, Color.DarkCyan, Color.DarkMagenta, Color.Brown)
            Next
            GISProjectPath = IO.Path.GetDirectoryName(MainWRDB.MapWin.Project.FileName)
        End If
    End Sub

    Private Sub frmMainMW_Shown(sender As Object, e As System.EventArgs) Handles Me.Shown
        ResetAll()
    End Sub

    Private Sub frmMainMW_FormClosed(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosedEventArgs) Handles Me.FormClosed
        SaveSetting(REGAPP, "General", "AutoRefresh", chkRefresh.Checked)
        If WRDBShapefile IsNot Nothing Then WRDBShapefile.Close()
        'WRDB.CloseWRDB()
        MainWRDB.RaiseFormClosed()
    End Sub

    ''' <summary>
    ''' Import selected data downloaded by BASINS into the current project and table
    ''' NOTE: caller must set GISProjectPath first
    ''' </summary>
    Public Sub GISImport()
        Try
            'must be a working table
            If ActiveBrowser Is Nothing OrElse ActiveBrowser.TableType <> clsProject.enumTableTypes.Working Then
                WarningMsg("You must open a Working table before you can import GIS data.")
                Exit Sub
            End If
            'see if is legacy non-index data table; if so, offer to upgrade
            If Not MainForm.CheckDataTableStructure(ActiveBrowser.TableName, True) Then Exit Sub
            Dim WRDBImport As New WRDB.Import.clsWRDBImport(PrintDoc, Project)
            MainForm.InitializeImport(WRDBImport, True)
            SuspendMapUpdate = True
            With New frmImportGIS(GISProjectPath, WRDBImport)
                .ShowDialog()
                .Dispose()
            End With
            SuspendMapUpdate = False
            CType(MainForm, frmMainMW).ResetAll()
            RefreshAllForms()
        Catch ex As Exception
            ErrorMsg(, ex)
        End Try
    End Sub

    ''' <summary>
    ''' Called when MapWindow selects stations and requests graph
    ''' </summary>
    Public Sub GraphSelectedStations()
        Try
            If SelectedStations Is Nothing OrElse SelectedStations.Count = 0 Then
                WarningMsg("You must select one or more stations on the map before you can graph data.")
                Exit Sub
            End If

            If Mode <> enumMode.Output OrElse cboDisplay.SelectedIndex = 0 Then
                WarningMsg("You can only graph selected stations if you have opened a data table and are displaying something other than 'Station Locations'.")
                Exit Sub
            End If

            If btnRefresh.Enabled Then btnRefresh.PerformClick() 'force a refresh 

            Dim found As Boolean = False
            'first, look for open timeseries graph form 
            For Each frm As Form In Application.OpenForms
                If TypeOf frm Is Graph.frmGraph Then
                    found = True
                    Exit For
                End If
            Next

            'if no graph forms open, create a new one
            If Not found Then
                Dim g As New Graph.clsGraph
                Dim SQLString As String = FormatSQL(IniFile.GetKey(clsWRDBIniFile.enumSection.Application, clsWRDBIniFile.enumKey.AppLastQuerySQL))
                'g.ShowGraph(Project.Name, clsProject.TempData, Graph.enumGraphType.TimeSeries, True)
                g.ShowGraph(Project.Name, ActiveBrowser.FullTableName, Graph.enumGraphType.TimeSeries, True, SQLString)
            End If

            'now update all graph forms
            For Each frm As Form In Application.OpenForms
                If TypeOf frm Is Graph.frmGraph Then
                    With CType(frm, Graph.frmGraph)
                        .AddGraphTab()
                        For i As Integer = 0 To SelectedStations.Count - 1
                            Dim StationID As String = SelectedStations(i)
                            Dim PCode As String
                            With CType(MainForm, frmMainMW).cboPCode
                                PCode = Project.DB.GetPickList(.Text)
                            End With
                            .AddSeries(StationID, PCode)
                        Next
                    End With
                    Exit Sub
                End If
            Next
        Catch ex As Exception
            ErrorMsg(, ex)
        End Try
    End Sub

    Friend Sub MapExtentsChanged()
        lstCoords.Clear()
        MainWRDB.MapWin.View.CursorMode = MapWinGIS.tkCursorMode.cmSelection
    End Sub

    Friend Sub MapMouseMove(ByVal ScreenX As Integer, ByVal ScreenY As Integer)
        Static lasttxt As String = ""

        Try

            'If Not ActiveForm Is Me Or IsSelecting Then Exit Sub

            If MainWRDB.GISMap.CursorMode <> MapWinGIS.tkCursorMode.cmSelection Or WRDBShapefile Is Nothing Or (Mode = enumMode.Output And dtResults Is Nothing) Then Exit Sub

            Dim x, y As Double
            MainWRDB.GISMap.PixelToProj(ScreenX, ScreenY, x, y)

            Dim txt As String = SelectedStationList() & vbCrLf & vbCrLf

            Dim closeShapes As Generic.List(Of Integer) = FindShapes(ScreenX, ScreenY)

            For Each rec As Integer In closeShapes
                With WRDBShapefile
                    If Mode = enumMode.Output And cboDisplay.SelectedIndex <> 0 Then
                        Dim StationID As String = TestNull(.CellValue(enumField.ID, rec), "")
                        Dim PCode As String = StringSplit(cboPCode.Text, " - ")(0)
                        If StationID.Contains("'") Or PCode.Contains("'") Then
                            WarningMsgFmt("The Station ID and PCode must not contain the single quote character: {0}; {1}", StationID, PCode)
                            Exit For
                        End If
                        Dim sel() As DataRow = dtResults.Select(String.Format("Station_ID='{0}' AND PCode='{1}'", StationID, PCode))
                        For i As Integer = 0 To sel.Length - 1
                            txt &= String.Format("Station ID: {0}\n{1}\nNo. Data: {2}\nMin Value: {3:0.000}\nMax Value: {4:0.000}\nAvg Value: {5:0.000}\nFirst Date: {6:d}\nLast Date: {7:d}\n------------------------------\n", _
                                    .CellValue(enumField.ID, rec), .CellValue(enumField.Name, rec), sel(i).Item("NumResult"), sel(i).Item("MinResult"), sel(i).Item("MaxResult"), sel(i).Item("AvgResult"), sel(i).Item("MinDate"), sel(i).Item("MaxDate")).Replace("\n", vbCrLf)
                        Next
                    Else
                        If Project.GisQuickTable Then
                            txt &= String.Format("Station ID: {0}\n{1}\nType: {2}\n------------------------------\n", _
                            .CellValue(enumField.ID, rec), .CellValue(enumField.Name, rec), .CellValue(enumField.Type, rec)).Replace("\n", vbCrLf)
                        Else
                            txt &= String.Format("Station ID: {0}\n{1}\nType: {2}\nFreq: {3}\nElev: {4}\n------------------------------\n", _
                            .CellValue(enumField.ID, rec), .CellValue(enumField.Name, rec), .CellValue(enumField.Type, rec), .CellValue(enumField.Freq, rec), .CellValue(enumField.Elev, rec)).Replace("\n", vbCrLf)
                        End If
                    End If
                End With
            Next

            If txt <> lasttxt Then
                lblInfo.Text = txt
                lasttxt = txt
            End If

        Catch ex As Exception

        End Try

    End Sub

    Friend Sub MapShapesSelected()
        lblInfo.Text = SelectedStationList()
        btnRefresh.Enabled = True
        If chkRefresh.Checked Then RefreshDisplay()
    End Sub

    Private Sub Panel1_ParentChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles Panel1.ParentChanged
        ReplaceTooltipAndHelpText(Me, Nothing, HelpProvider1)
    End Sub

    ''' <summary>
    ''' Reset display attributes (colors and/or sizes) of station points
    ''' </summary>
    Friend Sub RefreshDisplay()
        Try

            'If Not GisUtil.LayerVisible(WRDB.WRDBLayerName) Then Exit Sub
            MainWRDB.GISMap.set_ShapeLayerPointColor(WRDBLayerHandle, Graph.MapColor(MainWRDB.GISMap.get_ShapeLayerPointColor(WRDBLayerHandle)))
            If GisUtil.IsLayer(MainWRDB.WRDBLayerName) Then GisUtil.LayerVisible(MainWRDB.WRDBLayerName) = False

            If Mode = enumMode.Output Then
                Dim fldname As String = ""
                If cboDisplay.Text Like "*Number*" Then
                    fldname = "NumResult"
                ElseIf cboDisplay.Text Like "*Minimum*" Then
                    fldname = "MinResult"
                ElseIf cboDisplay.Text Like "*Maximum*" Then
                    fldname = "MaxResult"
                ElseIf cboDisplay.Text Like "*Average*" Then
                    fldname = "AvgResult"
                End If

                If fldname = "" Then 'displaying station location only for stations in current browser
                    With MainWRDB.GISMap
                        .set_ShapeLayerPointSize(WRDBLayerHandle, MainWRDB.GISMap.get_ShapeLayerPointSize(WRDBLayerHandle))
                        .set_ShapeLayerPointColor(WRDBLayerHandle, Graph.MapColor(Color.Black))
                    End With
                Else

                    WriteProgress("Updating display...")

                    'find min and max value for selected field
                    Dim minvalue As Single = Single.PositiveInfinity
                    Dim maxvalue As Single = Single.NegativeInfinity

                    Dim PCode As String = StringSplit(cboPCode.Text, " - ")(0)

                    With dtResults.DefaultView
                        .RowFilter = String.Format("PCode='{0}'", PCode)
                        .Sort = "Station_ID"
                        For r As Integer = 0 To .Count - 1
                            Dim value As Single = TestNull(.Item(r).Item(fldname), 0)
                            If value <> 0 Then
                                minvalue = Math.Min(minvalue, value)
                                maxvalue = Math.Max(maxvalue, value)
                            End If
                        Next
                    End With

                    Const minsize As Integer = 4, maxsize As Integer = 16

                    With MainWRDB.GISMap
                        For r As Integer = 0 To WRDBShapefile.NumShapes - 1
                            Dim StationID As String = WRDBShapefile.CellValue(0, r)

                            Dim row As Integer = dtResults.DefaultView.Find(StationID)
                            Dim value As Single = 0
                            If row <> -1 Then
                                value = TestNull(dtResults.DefaultView.Item(row).Item(fldname), 0)
                            End If
                            If value <> 0 Then
                                Dim size As Single = (value - minvalue) / (maxvalue - minvalue + 0.0001) * (maxsize - minsize) + minsize
                                .set_ShapePointSize(WRDBLayerHandle, r, size)
                                .set_ShapeVisible(WRDBLayerHandle, r, True)
                            Else
                                .set_ShapeVisible(WRDBLayerHandle, r, False)
                            End If
                            If Not MainForm.WriteProgress(r, WRDBShapefile.NumShapes - 1, "Updating display...", ProgressBarStyle.Blocks, True) Then Exit For
                        Next
                    End With
                    'reselect shapes
                    Dim SelectedShapes As New Generic.List(Of Integer)
                    With MainWRDB.MapWin.View.SelectedShapes
                        For i As Integer = 0 To .NumSelected - 1
                            SelectedShapes.Add(.Item(i).ShapeIndex)
                        Next
                        .ClearSelectedShapes()
                        For Each ShapeIndex As Integer In SelectedShapes
                            .AddByIndex(ShapeIndex, MainWRDB.MapWin.View.SelectColor)
                        Next
                    End With
                End If
                If True Or MustFillLists Then ExecuteQuery() 'so will be available for summary reports
            Else
                If MustCreateLayer Then CreateLayer()

                MainWRDB.MapWin.View.ClearSelectedShapes()

                'set color based on unique value of station type and display for all stations
                MainWRDB.GISMap.set_ShapeLayerPointSize(WRDBLayerHandle, MainWRDB.GISMap.get_ShapeLayerPointSize(WRDBLayerHandle))
                MainWRDB.GISMap.set_ShapeLayerPointColor(WRDBLayerHandle, Graph.MapColor(Color.Black))
                If cboDisplay.Items.Count > 1 Then 'color by station type
                    For r As Integer = 0 To WRDBShapefile.NumShapes - 1
                        Dim value As String = TestNull(WRDBShapefile.CellValue(enumField.Type, r), "")
                        Dim ptcolor As Color = Color.Black
                        If value = cboDisplay.Text Or cboDisplay.SelectedIndex = 0 Then
                            If value <> "" Then
                                Dim index As Integer = cboDisplay.Items.IndexOf(value)
                                If index <> -1 Then ptcolor = Graph.DefaultLayerColor(index - 1)
                            End If
                            MainWRDB.GISMap.set_ShapeVisible(WRDBLayerHandle, r, True)
                        Else
                            MainWRDB.GISMap.set_ShapeVisible(WRDBLayerHandle, r, False)
                        End If
                        MainWRDB.GISMap.set_ShapePointColor(WRDBLayerHandle, r, Graph.MapColor(ptcolor))
                    Next
                End If
            End If
            btnRefresh.Enabled = False
            lblInfo.Text = SelectedStationList()
            If GisUtil.IsLayer(MainWRDB.WRDBLayerName) Then GisUtil.LayerVisible(MainWRDB.WRDBLayerName) = True
        Catch ex As Exception
            ErrorMsg(, ex)
        Finally
            MainForm.ProgressComplete()
        End Try
    End Sub

    Friend Sub ResetAll()
        Try
            If SuspendMapUpdate Then Exit Sub
            HasBeenQueried = False
            Dim tblname As String
            Dim ProjectName As String
            If Project Is Nothing Then ProjectName = "None" Else ProjectName = Project.Name
            lblInfo.Text = String.Format("Current WRDB Project: {0}\n", ProjectName).Replace("\n", vbCrLf)
            If ActiveBrowser Is Nothing Then
                tblname = "None"
                With cboDisplay
                    .Sorted = True
                    .Items.Clear()
                    .Items.Add("(All Station Types)")
                    If Project.DB.TableExists("Stations") Then .Items.AddRange(Project.DB.GetRecordList("Stations", "Station_Type").ToArray)
                    If .Items.Contains("") Then .Items.Remove("")
                End With
                grpDisplay.Text = "Display by Station Type"
                cboPCode.Items.Clear()
                cboCCode.Items.Clear()
                txtDateTime.Clear()
                grpPCode.Enabled = False
                lblInfo.Text &= vbCrLf & "Open a Working or Master table to display a thematic map showing the areal distribution of the data."
                cboDisplay.SelectedIndex = 0 'station locations
                Mode = enumMode.Display
                MustFillLists = True
                MustCreateLayer = True
            Else
                tblname = ActiveBrowser.TableName
                lblInfo.Text = String.Format("Active WRDB Table: {0}\n\n", tblname).Replace("\n", vbCrLf)
                With cboDisplay
                    .Items.Clear()
                    .Sorted = False
                    .Items.Add("Station Location")
                    .Items.Add("Number of Observations")
                    .Items.Add("Minimum Value")
                    .Items.Add("Maximum Value")
                    .Items.Add("Average Value")
                End With
                grpDisplay.Text = "Display by Summary Type"
                grpDisplay.Enabled = True
                grpPCode.Enabled = False

                lblInfo.Text &= "The unique stations found in the currently active browser table are displayed. Select a summary statistic and then the desired PCode (and CCode && Date range) of interest to display a thematic map. Select stations on the map to display time series graphs." & vbCrLf & vbCrLf & "When the Select tool is activated, you can select stations for further analysis on the screen, and when you position your mouse over a WRDB station, important statistics will appear in this window."
                cboDisplay.SelectedIndex = 0 'station locations

                'dtResults is filled in SummarizeStationData; it will be filled the first time that something other than Station Location is selected
                If dtResults IsNot Nothing Then dtResults.Dispose()
                dtResults = Nothing
                MustSummarize = True
                MustFillLists = True
                MustCreateLayer = True
                Mode = enumMode.Output
            End If

            btnRefresh.Enabled = True
            If chkRefresh.Checked Then btnRefresh.PerformClick()

            MainWRDB.MapWin.View.CursorMode = MapWinGIS.tkCursorMode.cmSelection
            EnableBrowserMenus()
        Catch ex As Exception
            ErrorMsg(, ex)
        Finally
            ProgressComplete()
        End Try
    End Sub

    Public Sub SaveAs()
        'Try

        '    Dim NewName As String = InputBox("This will copy the automatically generated WRDB display layer to a new shape file and layer. Enter the name for the new layer:", "Save WRDB Layer As", LastDisplay)
        '    If NewName.Trim = "" Then Exit Sub
        '    Dim FileName As String = String.Format("{0}\{1}.shp", WRDBShapeDirectory, NewName)
        '    For i As Integer = 0 To g_MapWin.Layers.NumLayers - 1
        '        With g_MapWin.Layers(i)
        '            If .Name.ToUpper = NewName.ToUpper Or IO.Path.GetFileNameWithoutExtension(.FileName).ToUpper = NewName.ToUpper Then
        '                MessageBox.Show("A layer or shape file with this name already exists; please try another layer name.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
        '                Exit Sub
        '            End If
        '        End With
        '    Next

        '    'see if shape file exists, even if it is not loaded
        '    If My.Computer.FileSystem.FileExists(FileName) AndAlso MessageBox.Show("A shape file with this name already exists (although it is not loaded into this BASINS project); do you want to overwrite it?", "Warning", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning) = DialogResult.Cancel Then Exit Sub

        '    'copy all the files
        '    Application.UseWaitCursor = True
        '    g_MapWin.StatusBar.Item(3).Text = "Copying shape file..."
        '    Dim ThisFileName As String = WRDBShapeDirectory & "\WRDB Stations.shp"
        '    For i As Int16 = 1 To 5
        '        Dim ext As String = Choose(i, "shp", "shx", "dbf", "prj", "mwsr")
        '        If IO.File.Exists(IO.Path.ChangeExtension(ThisFileName, ext)) Then IO.File.Copy(IO.Path.ChangeExtension(ThisFileName, ext), IO.Path.ChangeExtension(FileName, ext), True)
        '    Next

        '    'open the new shapefile
        '    Dim sf As New MapWinGIS.Shapefile
        '    If Not sf.Open(IO.Path.ChangeExtension(FileName, ".shp")) Then Exit Sub

        '    'create a coloring scheme (note that pnt.z contains the desired values)

        '    g_MapWin.StatusBar.Item(3).Text = "Creating color scheme..."

        '    Dim FieldName As String = LastDisplay

        '    'add to project and assign to group

        '    Dim NewLayer As MapWindow.Interfaces.Layer = g_MapWin.Layers.Add(sf, WRDBLayerName, 0, 0, 6)
        '    With NewLayer
        '        .Name = NewName
        '        NewLayer.Color = Drawing.Color.Cyan
        '        .LineOrPointSize = 12
        '        .UseTransparentColor = False
        '        .PointType = MapWinGIS.tkPointType.ptCircle
        '        .SkipOverDuringSave = False
        '        .GroupHandle = GetWRDBGroupHandle()
        '    End With

        '    'assign colorscheme

        '    If FieldName <> "" Then
        '        Dim colorScheme As New MapWinGIS.ShapefileColorScheme

        '        For i As Integer = 0 To sf.NumFields - 1
        '            If sf.Field(i).Name = FieldName Then colorScheme.FieldIndex = i : Exit For
        '        Next

        '        'find range of values
        '        Dim minvalue As Double = Double.MaxValue
        '        Dim maxvalue As Double = Double.MinValue
        '        For i As Integer = 0 To sf.NumShapes - 1
        '            Dim value As Object = sf.CellValue(colorScheme.FieldIndex, i)
        '            If Not IsDBNull(value) Then
        '                minvalue = Math.Min(minvalue, value)
        '                maxvalue = Math.Max(maxvalue, value)
        '            End If
        '        Next
        '        If minvalue <> maxvalue And minvalue <> Double.MaxValue Then
        '            Dim colorBreak As MapWinGIS.ShapefileColorBreak
        '            colorBreak = New MapWinGIS.ShapefileColorBreak
        '            'With colorBreak
        '            '    .Caption = "None"
        '            '    .StartValue = DBNull.Value
        '            '    .EndValue = DBNull.Value
        '            '    .StartColor = System.Convert.ToUInt32(System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.Gainsboro))
        '            '    .EndColor = System.Convert.ToUInt32(System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.Gainsboro))
        '            'End With
        '            'colorScheme.Add(colorBreak)

        '            For i As Integer = 0 To 3
        '                colorBreak = New MapWinGIS.ShapefileColorBreak
        '                With colorBreak
        '                    Dim mn As Double = minvalue + (maxvalue - minvalue) * i / 4
        '                    Dim mx As Double = minvalue + (maxvalue - minvalue) * (i + 1) / 4
        '                    .Caption = String.Format("{0:0.00}-{1:0.00}", mn, mx)
        '                    .StartValue = mn
        '                    .EndValue = mx
        '                    .StartColor = System.Convert.ToUInt32(System.Drawing.ColorTranslator.ToOle(Choose(i + 1, Drawing.Color.Blue, Drawing.Color.Green, Drawing.Color.Yellow, Drawing.Color.Red, Drawing.Color.LightPink)))
        '                    .EndColor = System.Convert.ToUInt32(System.Drawing.ColorTranslator.ToOle(Choose(i + 2, Drawing.Color.Blue, Drawing.Color.Green, Drawing.Color.Yellow, Drawing.Color.Red, Drawing.Color.LightPink)))
        '                End With
        '                colorScheme.Add(colorBreak)
        '            Next
        '            If colorScheme.NumBreaks > 0 Then NewLayer.ColoringScheme = colorScheme
        '        End If

        '    End If
        'Catch ex As Exception
        '    MessageBox.Show(ex.ToString, "Unhandled Error Has Occurred", MessageBoxButtons.OK, MessageBoxIcon.Error)
        'Finally
        '    g_MapWin.StatusBar.Item(3).Text = ""
        '    Application.UseWaitCursor = False
        'End Try
    End Sub

    ''' <summary>
    ''' Only call this when displaying data by pcode
    ''' </summary>
    ''' <remarks></remarks>
    Friend Sub SummarizeStationData()
        Try
            Try
                With Project
                    MainForm.WriteProgress("Summarizing...", ProgressBarStyle.Marquee)
                    'query all stations in support table (or referenced in active working/master or temp table) 
                    Select Case Mode
                        Case enumMode.Output
                            'Dim Where As String = ""
                            'If Not txtDateTime.Text.StartsWith("(") Then Where = "WHERE " & IIf(txtDateTime.Text.ToUpper.Contains("DATE_TIME"), "", "Date_Time ") & txtDateTime.Text & " "
                            'If Not cboCCode.Text.StartsWith("(") Then Where = IIf(Where = "", "WHERE ", " AND ") & "CCode = '" & StringSplit(cboCCode.Text, " - ")(0) & "' "
                            'Dim Sql As String = String.Format( _
                            '"SELECT Station_ID, PCode, " & _
                            '"COUNT(Result) as NumResult, " & _
                            '"MIN(Result) as MinResult, " & _
                            '"MAX(Result) as MaxResult, " & _
                            '"AVG(Result) as AvgResult, " & _
                            '"MIN(Date_Time) as MinDate, " & _
                            '"MAX(Date_Time) as MaxDate " & _
                            '"FROM {0} " & _
                            'Where & _
                            '"GROUP BY Station_ID,PCode", ActiveBrowser.TableName, txtDateTime.Text)

                            Dim Where As String = "WHERE PCODE = '" & StringSplit(cboPCode.Text, " - ")(0) & "' "
                            If Not txtDateTime.Text.StartsWith("(") Then Where &= "AND " & IIf(txtDateTime.Text.ToUpper.Contains("DATE_TIME"), "", "Date_Time ") & txtDateTime.Text & " "
                            If Not cboCCode.Text.StartsWith("(") Then Where &= "AND CCode = '" & StringSplit(cboCCode.Text, " - ")(0) & "' "

                            Dim Sql As String = String.Format( _
                            "SELECT Station_ID, MIN(PCode) as PCode, " & _
                            "COUNT(Result) as NumResult, " & _
                            "MIN(Result) as MinResult, " & _
                            "MAX(Result) as MaxResult, " & _
                            "AVG(Result) as AvgResult, " & _
                            "MIN(Date_Time) as MinDate, " & _
                            "MAX(Date_Time) as MaxDate " & _
                            "FROM {0} " & _
                            Where & _
                            "GROUP BY Station_ID", ActiveBrowser.TableName, txtDateTime.Text)
                            If Not .DB.AddTable(dtResults, Sql) Then Exit Sub
                            dtResults.PrimaryKey = New DataColumn() {dtResults.Columns("Station_ID"), dtResults.Columns("PCode")}
                    End Select
                End With
                MustSummarize = False
            Catch ex As Exception
                ErrorMsg(, ex)
            Finally
                MainForm.ProgressComplete()
            End Try
        Catch ex As Exception
            ErrorMsg(, ex)
            MainForm.ProgressComplete()
        End Try
    End Sub

End Class

''' <summary>
''' This class is used when I call MapWindow functions which need a callback function
''' </summary>
Public Class clsMWCallback
    Implements MapWinGIS.ICallback

    Public Sub [Error](ByVal Key As String, ByVal ErrMsg As String) Implements MapWinGIS.ICallback.Error
        ErrorMsg("MapWindow Error: " & ErrMsg)
    End Sub

    Public Sub Progress(ByVal Key As String, ByVal Percent As Integer, ByVal Message As String) Implements MapWinGIS.ICallback.Progress
        MainForm.WriteProgress(Percent, 100, Message, ProgressBarStyle.Blocks, False)
    End Sub
End Class

